﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Diagnostics;

namespace LowLevelGraphics.ColorSpaces
{
    /// <summary>
    /// Hunterlab Channel
    /// </summary>
    public enum HunterLabChannel
    {
        /// <summary>
        /// 
        /// </summary>
        L = 0,
        /// <summary>
        /// 
        /// </summary>
        a = 1,
        /// <summary>
        /// 
        /// </summary>
        b = 2
    }

    /// <summary>
    /// 
    /// </summary>
    [DebuggerDisplay("L: {m_L}, a: {m_u}, b: {m_b}")]
    public class HunterLab : AbstractColorSpace
    {
        protected double m_L = 0.0f;
        protected double m_a = 0.0f;
        protected double m_b = 0.0f;

        /// <summary>
        /// Initializes a new instance of the <see cref="HunterLab"/> class.
        /// </summary>
        /// <param name="_color">The _color.</param>
        public HunterLab(Color _color)
            : base(_color)
        {
            
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="HunterLab"/> class.
        /// </summary>
        /// <param name="_L">The _ L.</param>
        /// <param name="_a">The _a.</param>
        /// <param name="_b">The _b.</param>
        public HunterLab(double _L, double _a, double _b)
        {
            m_L = _L;
            m_a = _a;
            m_b = _b;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_hunterlab"></param>
        internal HunterLab(HunterLab _hunterlab)
        {
            this.m_Color = _hunterlab.m_Color;
            this.m_L = _hunterlab.m_L;
            this.m_a = _hunterlab.m_a;
            this.m_b = _hunterlab.m_b;
        }

        /// <summary>
        /// Enable casting into operator
        /// </summary>
        /// <param name="_color"></param>
        /// <returns></returns>
        public static explicit operator HunterLab(Color _color)
        {
            return new HunterLab(_color);
        }

        /// <summary>
        /// reads or sets l
        /// </summary>
        public double L
        {
            get { return m_L; }
            set { m_L = value; }
        }

        /// <summary>
        /// reads or sets a
        /// </summary>
        public double a
        {
            get { return m_a; }
            set { m_a = value; }
        }

        /// <summary>
        /// reads or sets b
        /// </summary>
        public double b
        {
            get { return m_b; }
            set { m_b = value;}
        }

        /// <summary>
        /// Convert into this color space
        /// </summary>
        protected override void CalcValues()
        {
            CIEXYZ xyz = new CIEXYZ(m_Color);
            m_L = 10 * Math.Sqrt( xyz.Y );
            m_a = 17.5 * (((1.02 * xyz.X) - xyz.Y) / Math.Sqrt(xyz.Y));
            m_b = 7 * ( ( xyz.Y - ( 0.847 * xyz.Z ) ) / Math.Sqrt( xyz.Y ) );
        }

        /// <summary>
        /// retransform to rgb color space
        /// </summary>
        /// <returns></returns>
        public override Color ToColor()
        {
                double var_Y = m_L / 10;
                double var_X = m_a / 17.5 * m_L / 10;
                double var_Z = m_b / 7 * m_L / 10;

                double Y = var_Y * var_Y;
                double X = (var_X + Y) / 1.02;
                double Z = -( var_Z - Y ) / 0.847;

                CIEXYZ xyz = new CIEXYZ(X,Y,Z);
                return xyz.ToColor();
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return string.Format("Color L = {0}, a = {1}, b = {2}", m_L, m_a, m_b);
        }

        /// <summary>
        /// Gets the values.
        /// </summary>
        /// <returns></returns>
        public override object[] GetValues()
        {
            return new object[] { m_L, m_a, m_b };
        }

        /// <summary>
        /// Sets the values.
        /// </summary>
        /// <param name="_aObject">The _a object.</param>
        public override void SetValues(object[] _aObject)
        {
            this.m_L = (double)_aObject[0];
            this.m_a = (double)_aObject[1];
            this.m_b = (double)_aObject[2];
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new HunterLab(this);
        }
    }
}
